package com.uuah.server.component;

import com.uuah.api.config.object.IObjectFactory;
import com.uuah.api.lifecycle.InitialisationCallback;
import com.uuah.config.PoolingProfile;
import com.uuah.exception.AbstractUuahException;
import com.uuah.exception.lifecycle.InitialisationException;
import com.uuah.pool.ILifecyleEnabledObjectPool;
import com.uuah.pool.LifecycleEnabledObjectPool;
import com.uuah.server.UuahServer;
import com.uuah.server.api.component.ILifecycleAdapter;
import com.uuah.server.api.component.model.IEntryPointResolverSet;

public class PooledJavaComponent extends AbstractComponent {

	protected PoolingProfile poolingProfile;
	protected ILifecyleEnabledObjectPool lifecycleAdapterPool;

	public PooledJavaComponent() {
		super();
	}

	public PooledJavaComponent(IObjectFactory objectFactory) {
		this(objectFactory, null);
	}

	public PooledJavaComponent(IObjectFactory objectFactory,
			PoolingProfile poolingProfile) {
		super(objectFactory);
		this.poolingProfile = poolingProfile;
	}

	public PooledJavaComponent(IObjectFactory objectFactory,
			PoolingProfile poolingProfile,
			IEntryPointResolverSet entryPointResolverSet) {
		super(objectFactory, entryPointResolverSet);
		this.poolingProfile = poolingProfile;
	}

	protected ILifecycleAdapter borrowComponentLifecycleAdaptor()
			throws Exception {
		return (ILifecycleAdapter) lifecycleAdapterPool.borrowObject();
	}

	protected void returnComponentLifecycleAdaptor(
			ILifecycleAdapter lifecycleAdapter) {
		lifecycleAdapterPool.returnObject(lifecycleAdapter);
	}

	protected void doStart() throws AbstractUuahException {
		super.doStart();
		lifecycleAdapterPool = new LifecycleEnabledObjectPool(
				new LifeCycleAdaptorFactory(), poolingProfile);
		lifecycleAdapterPool.initialise();
		lifecycleAdapterPool.start();

		UuahServer.getServerStats().setThreadPoolSize(
				poolingProfile.getMaxActive());
	}

	protected void doStop() throws AbstractUuahException {
		super.doStop();
		if (lifecycleAdapterPool != null) {
			lifecycleAdapterPool.stop();
			lifecycleAdapterPool.close();
			lifecycleAdapterPool = null;
		}
	}

	public void setPoolingProfile(PoolingProfile poolingProfile) {
		this.poolingProfile = poolingProfile;
	}

	public PoolingProfile getPoolingProfile() {
		return poolingProfile;
	}

	protected class LifeCycleAdaptorFactory implements IObjectFactory {

		public Object getInstance() throws Exception {
			return createLifeCycleAdaptor();
		}

		public Class getObjectClass() {
			return ILifecycleAdapter.class;
		}

		public void initialise() throws InitialisationException {
			objectFactory.initialise();
		}

		public void dispose() {
			objectFactory.dispose();
		}

		public void addObjectInitialisationCallback(
				InitialisationCallback callback) {
			objectFactory.addObjectInitialisationCallback(callback);
		}

		public boolean isSingleton() {
			return false;
		}
	}

}
